/**
 * 
 */
package com.shine.icis.blo.imp;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.shine.icis.blo.IFlowService;
import com.shine.icis.dao.IFlowDAO;
import com.shine.icis.flow.handler.IFlowHandler;
import com.shine.icis.flow.handler.INodeHandler;
import com.shine.icis.hbean.FlowDef;
import com.shine.icis.hbean.FlowIns;
import com.shine.icis.hbean.FlowNode;
import com.shine.icis.hbean.FlowVar;
import com.shine.icis.hbean.NodeAssign;
import com.shine.icis.hbean.TaskIns;

/**
 * @author zsy
 *
 */
public class FlowService implements IFlowService {
	
	private IFlowDAO flowDAO;
	
	public void setFlowDAO(IFlowDAO flowDAO) {
		this.flowDAO = flowDAO;
	}
	
	@Override
	public FlowIns txNewFlowIns(String flowDefId, List<FlowVar> vars) {
		FlowDef fd = flowDAO.findFlowDefById(flowDefId);
		if (fd == null) {
			throw new IllegalArgumentException("流程定义不存在：" + flowDefId);
		}
		FlowIns fi = new FlowIns();
		fi.setFlowDef(fd);
		fi.setInsName(fd.getFlowName());
		fi.setCreateTime(new Date());
		if (vars != null && !vars.isEmpty()) {
			for (FlowVar v : vars) {
				fi.addFlowVar(v);
			}
		}
		
		flowDAO.save(fi);
		return fi;
	}

	@Override
	public TaskIns txToNextNode(String flowInsId, boolean toFirst) throws Exception {
		FlowIns fi = flowDAO.findFlowInsById(flowInsId);
		if (fi == null) {
			throw new IllegalArgumentException("流程实例不存在：" + flowInsId);
		}
		String currentNodeId = toFirst || fi.getFlowNode() == null ? null : fi.getFlowNode().getNodeId();
		FlowNode fn = flowDAO.findNextNode(fi.getFlowDef().getFlowId(), currentNodeId);
		TaskIns ti = null;
		if (fn != null) {
			ti = new TaskIns();
			ti.setFlowIns(fi);
			ti.setFlowNode(fn);
			ti.setTaskName(fn.getNodeName());
			ti.setTaskStatus(TaskIns.TASK_STATUS_CREATE);
			ti.setCreateTime(new Date());
			flowDAO.save(ti);
		} else {//没有下一个步骤节点，把流程实例结束
			fi.setEndTime(new Date());
			//触发结束事件
			if (fi.getFlowDef().getActionHandler() != null) {
//				try {
				Class<?> hClass = Class.forName(fi.getFlowDef().getActionHandler());
				IFlowHandler hObj = (IFlowHandler)hClass.newInstance();
				hObj.execute(fi);
//				} catch (Exception e) {
//					e.printStackTrace();
//				}
			}
			
		}
		fi.setFlowNode(fn);//记录当前步骤
		flowDAO.update(fi);
		return ti;
	}
	
	@Override
	public TaskIns txEndTask(String taskId, String actorId, String comment) throws Exception {
		TaskIns ti = flowDAO.findTaskById(taskId);
		if (ti == null) {
			throw new IllegalArgumentException();
		}
		ti.setActorId(actorId);
		ti.setComment(comment);
		ti.setTaskStatus(TaskIns.TASK_STATUS_END);
		ti.setEndTime(new Date());
		//触发结束事件
		if (ti.getFlowNode().getActionHandler() != null) {
//			try {
			Class<?> hClass = Class.forName(ti.getFlowNode().getActionHandler());
			INodeHandler hObj = (INodeHandler)hClass.newInstance();
			hObj.execute(ti);
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
		}
		
		flowDAO.update(ti);
		return ti;
	}
	
	@Override
	public FlowIns txForceEndFlowIns(String flowInsId) {
		FlowIns fi = flowDAO.findFlowInsById(flowInsId);
		if (fi == null) {
			throw new IllegalArgumentException("流程实例不存在：" + flowInsId);
		}
		Set<TaskIns> tis = fi.getTaskInses();
		if (tis != null && !tis.isEmpty()) {
			for (TaskIns ti : tis) {
				if(ti.getTaskStatus() != TaskIns.TASK_STATUS_END) {
					ti.setTaskStatus(TaskIns.TASK_STATUS_END);
					flowDAO.update(ti);
				}
			}
		}
		fi.setFlowNode(null);
		fi.setEndTime(new Date());
		flowDAO.update(fi);
		return fi;
	}

	@Override
	public List<TaskIns> getTasks(String userId, List<String> roleIds) {
		return flowDAO.findTasks(userId, roleIds);
	}
	
	@Override
	public List<TaskIns> getEndTasks(String flowInsId) {
		return flowDAO.findEndTasks(flowInsId);
	}

	@Override
	public boolean csFirstNode(String taskId) {
		if (taskId == null) {
			throw new IllegalArgumentException();
		}
		TaskIns ti = flowDAO.findTaskById(taskId);
		if (ti == null) {
			throw new IllegalArgumentException();
		}
		if (ti.getFlowNode() == null || ti.getFlowNode().getFlowDef() == null) {
			throw new IllegalArgumentException();
		}
		return flowDAO.testFirstNode(ti.getFlowNode().getFlowDef().getFlowId(), ti.getFlowNode().getNodeId());
	}
	
	@Override
	public void addFlowNode(String flowId, String nodeName,
			String actionHandler, String[] assignUsers) {
		if (flowId == null || nodeName == null || assignUsers == null) {
			throw new IllegalArgumentException();
		}
		FlowDef def = flowDAO.findFlowDefById(flowId);
		if (def == null) {
			throw new IllegalArgumentException("流程定义不存在");
		}
		FlowNode node = new FlowNode();
		node.setFlowDef(def);
		node.setNodeName(nodeName);
		node.setActionHandler(actionHandler);
		int maxOrder = flowDAO.findFlowNodeNextOrderCode(flowId);
		node.setOrderCode(maxOrder + 1);
		Set<NodeAssign> nas = new HashSet<NodeAssign>(assignUsers.length);
		for (String user : assignUsers) {
			NodeAssign na = new NodeAssign();
			na.setAssignValue(user);
			na.setAssignType(NodeAssign.ASSIGN_TYPE_USER);
			nas.add(na);
		}
		node.setNodeAssigns(nas);
		flowDAO.save(node);
	}

	@Override
	public void modifyFlowNode(String nodeId, String nodeName,
			String actionHandler, String[] assignUsers) {
		if (nodeId == null || nodeName == null || assignUsers == null) {
			throw new IllegalArgumentException();
		}
		FlowNode node = flowDAO.findFlowNodeById(nodeId);
		if (node == null) {
			throw new IllegalArgumentException("流程步骤不存在");
		}
		node.setNodeName(nodeName);
		node.setActionHandler(actionHandler);
		Set<NodeAssign> nas = node.getNodeAssigns();
		if (nas == null) {
			nas = new HashSet<NodeAssign>(assignUsers.length);
		} else {
			for (NodeAssign na : nas) {
				flowDAO.delete(na);
			}
			nas.clear();
		}
		for (String user : assignUsers) {
			NodeAssign na = new NodeAssign();
			na.setAssignValue(user);
			na.setAssignType(NodeAssign.ASSIGN_TYPE_USER);
			nas.add(na);
		}
		node.setNodeAssigns(nas);
		flowDAO.update(node);
	}

	@Override
	public void deleteFlowNode(String nodeId) {
		if (nodeId == null) {
			return;
		}

		flowDAO.deleteFlowNode(nodeId);
	}

	@Override
	public Collection<FlowNode> getFlowNodes(String flowId) {
		FlowDef def = flowDAO.findFlowDefById(flowId);
		if (def == null) {
			throw new IllegalArgumentException("流程定义不存在");
		}
		def.getFlowNodes().size();//init lazy
		return def.getFlowNodes();
	}

	@Override
	public void txSortFlowNode(String nodeId, boolean sortUp) {
		FlowNode cfn = flowDAO.findFlowNodeById(nodeId);
		FlowNode tfn = null;
		if (sortUp) {
			tfn = flowDAO.findPreviousNode(cfn.getFlowDef().getFlowId(), nodeId);
		} else {
			tfn = flowDAO.findNextNode(cfn.getFlowDef().getFlowId(), nodeId);
		}
		int orderCode = cfn.getOrderCode();
		cfn.setOrderCode(tfn.getOrderCode());
		tfn.setOrderCode(orderCode);
		flowDAO.update(cfn);
		flowDAO.update(tfn);
	}
	
}
